/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package simplemetrosystem.view;

import simplemetrosystem.view.Layout.GBC;
import java.awt.GridBagLayout;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import simplemetrosystem.control.Calculation.ModelManager;
import simplemetrosystem.control.ElementManager;
import simplemetrosystem.model.Element.Interface.HighLightable;
import simplemetrosystem.model.Element.MetroEdge;
import simplemetrosystem.model.Element.Interface.MetroElement;
import simplemetrosystem.model.Element.MetroLine;
import simplemetrosystem.model.Element.MetroStation;
import simplemetrosystem.model.charlanguage.NameMap;
import simplemetrosystem.view.table.AllEdgeTable;
import simplemetrosystem.view.table.AllEdgeTableToolPane;
import simplemetrosystem.view.table.AllLineTable;
import simplemetrosystem.view.table.AllLineTableToolPane;
import simplemetrosystem.view.table.AllStationTable;
import simplemetrosystem.view.table.AllStationTableToolPane;
import simplemetrosystem.view.table.CalculPane;
import simplemetrosystem.view.table.EdgeTable;
import simplemetrosystem.view.table.EdgeTableToolPane;
import simplemetrosystem.view.table.Exceptions.InformationPanelException;
import simplemetrosystem.view.table.LineTable;
import simplemetrosystem.view.table.LineTableToolPane;
import simplemetrosystem.view.table.StationTable;
import simplemetrosystem.view.table.StationTableToolPane;

/**
 * 信息编辑表格组件,负责用户对元素管理类的直接控制
 * 组件从画板类得到元素管理类的实例,并对其解析,生成全体线路,全体站点,全体关联三个子标签
 * 并对三个表格进行初始化,表格会根据用户的操作对进行相应修改,同时向画板类发出高亮显示事件
 * 
 * @author Eric Qian
 */
public class InformationPane extends JTabbedPane implements Observer {

    /**
     * 初始化信息面板
     * @param frame 软件框架
     */
    public InformationPane(MetroFrame frame) {
        super();
        this.frame = frame;
        nameMap = NameMap.getInstance();
        ElementManager.getInstance().addObserver(this);
        elemTab = ALL_LINE;
        //设置Tab在组件中的位置
        this.setTabPlacement(JTabbedPane.TOP);
        //设置Tab的排列方式
        this.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);

        addTabs();
        addChangeListener(new TabChangeListener());
    }

    /*
     * 初始化并排版标签
     */
    private void addTabs() {
        addTab(nameMap.getName("All lines"), getAllLinePane());
        addTab(nameMap.getName("All stations"), getAllStationPane());
        addTab(nameMap.getName("All edges"), getAllEdgePane());
    }

    /**
     * 得到软件框架
     * @return 软件框架
     */
    public MetroFrame getFrame() {
        return frame;
    }

    /**
     * 得到当前特殊元素
     * @return 特殊元素,若elemTab为INF_NULL无返回NULL
     */
    public MetroElement getElement() {
        if (elemTab != INF_NULL) {
            return currentElement;
        }
        return null;
    }

    /**
     * 
     * @param element
     * @param highLight 
     */
    public void setHighLight(MetroElement element, boolean highLight) {
        if (currentElement != null) {
            HighLightable aElement = (HighLightable) currentElement;
            aElement.setHighLight(false);
            frame.getMetroTabbedPane().getAllLineCanvas().repaint();
        }
        if (element != null) {
            if (element instanceof HighLightable) {
                currentElement = element;
                HighLightable aElement = (HighLightable) element;
                aElement.setHighLight(highLight);
                frame.getMetroTabbedPane().getAllLineCanvas().repaint();
            }
        }
    }

    /**
     * 设置当前表格关注点，进行画面跳转
     * @param tab 显示表格类型
     * @param element 
     * @throws InformationPanelException 若表格类型与表格元素不对应抛错
     */
    public void setFocus(int tab, MetroElement element) throws InformationPanelException {
        //移出额外标签
        removeExTab();
        currentElement = element;

        if (tab == ALL_LINE) {
            elemTab = INF_NULL;
            this.setSelectedIndex(ALL_LINE);
        } else if (tab == ALL_STATION) {
            elemTab = INF_NULL;
            this.setSelectedIndex(ALL_STATION);
        } else if (tab == ALL_EDGE) {
            elemTab = INF_NULL;
            this.setSelectedIndex(ALL_EDGE);
        } else if (tab == LINE) {
            elemTab = LINE;
            if (element instanceof MetroLine) {
                MetroLine line = (MetroLine) element;
                this.addTab(line.getDisplayName(), getLinePane(line));
                this.setSelectedIndex(EXTAB);
            } else {
                throw new InformationPanelException();
            }
        } else if (tab == STATION) {
            elemTab = STATION;
            if (element instanceof MetroStation) {
                MetroStation station = (MetroStation) element;
                this.addTab(station.getDisplayName(), getStationPane(station));
                this.setSelectedIndex(EXTAB);
            } else {
                throw new InformationPanelException();
            }

        } else if (tab == EDGE) {
            elemTab = EDGE;
            if (element instanceof MetroEdge) {
                MetroEdge edge = (MetroEdge) element;
                this.addTab(edge.getDisplayName(), getEdgePane(edge));
                this.setSelectedIndex(EXTAB);
            } else {
                throw new InformationPanelException();
            }
        } else if (tab == CALCUL) {
            addTab(nameMap.getName("Calculation"), newCalculPane());
            setSelectedIndex(EXTAB);
        }
    }

    /**
     * 设置额外标签
     * @param elemTab
     */
    public void setElemTab(int elemTab) {
        //System.out.println(elemTab);
        this.elemTab = elemTab;
    }

    /**
     * 移出额外标签
     */
    public void removeExTab() {
        if (getTabCount() == InformationPane.EXTAB + 1) {
            remove(InformationPane.EXTAB);
            elemTab = InformationPane.INF_NULL;
        }
    }

    /**
     * 得到全体关联工具条
     * @return
     */
    public AllEdgeTableToolPane getAllEdgeTablePane() {
        return allEdgeTablePane;
    }

    /**
     * 得到全体线路工具条
     * @return
     */
    public AllLineTableToolPane getAllLineTablePane() {
        return allLineTablePane;
    }

    /**
     * 得到全体站点工具条
     * @return
     */
    public AllStationTableToolPane getAllStationTablePane() {
        return allStationTablePane;
    }

    /**
     * 
     * @return
     */
    public AllEdgeTable getAllEdgeTable() {
        return allEdgeTable;
    }

    /**
     * 
     * @return
     */
    public AllLineTable getAllLineTable() {
        return allLineTable;
    }

    /**
     * 
     * @return
     */
    public AllStationTable getAllStationTable() {
        return allStationTable;
    }

    /**
     * 
     * @return
     */
    public int getElemTab() {
        return elemTab;
    }

    /**
     * 得到全体线路面板，面板为单例
     * @return 全体线路面板
     */
    public JPanel getAllLinePane() {
        if (allLinePane == null) {
            allLinePane = new JPanel();
            allLinePane.setLayout(new GridBagLayout());
            allLineTable = new AllLineTable(this);
            allLineTablePane = new AllLineTableToolPane(this);
            allLinePane.add(allLineTablePane, new GBC(0, 0).setWeight(100, 0).setFill(GBC.BOTH));
            allLinePane.add(new JScrollPane(allLineTable), new GBC(0, 1).setWeight(100, 100).setFill(GBC.BOTH));
        }
        return allLinePane;
    }

    /**
     *得到全体站点面板，面板为单例
     * @return 全体站点面板
     */
    public JPanel getAllStationPane() {
        if (allStationPane == null) {
            allStationPane = new JPanel();
            allStationPane.setLayout(new GridBagLayout());
            allStationTablePane = new AllStationTableToolPane(this);
            allStationTable = new AllStationTable(this);
            allStationPane.add(allStationTablePane, new GBC(0, 0).setWeight(100, 0).setFill(GBC.BOTH));
            allStationPane.add(new JScrollPane(allStationTable), new GBC(0, 1).setWeight(100, 100).setFill(GBC.BOTH));
        }
        return allStationPane;
    }

    /**
     * 得到全体关联面板，面板为单例
     * @return 全体关联面板
     */
    public JPanel getAllEdgePane() {
        if (allEdgePane == null) {
            allEdgePane = new JPanel();
            allEdgePane.setLayout(new GridBagLayout());
            allEdgeTablePane = new AllEdgeTableToolPane(this);
            allEdgeTable = new AllEdgeTable(this);
            allEdgePane.add(allEdgeTablePane, new GBC(0, 0).setWeight(100, 0).setFill(GBC.BOTH));
            allEdgePane.add(new JScrollPane(allEdgeTable), new GBC(0, 1).setWeight(100, 100).setFill(GBC.BOTH));
        }
        return allEdgePane;
    }

    /**
     * 得到单个线路信息面板
     * @param line 输入线路
     * @return 线路信息面板
     */
    public JPanel getLinePane(MetroLine line) {
        linePane = new JPanel();
        linePane.setLayout(new GridBagLayout());
        lineTablePane = new LineTableToolPane(this, line);
        lineTable = new LineTable(this, line);
        linePane.add(lineTablePane, new GBC(0, 0).setWeight(100, 0).setFill(GBC.BOTH));
        linePane.add(new JScrollPane(lineTable), new GBC(0, 1).setWeight(100, 100).setFill(GBC.BOTH));
        currentElement = line;
        return linePane;
    }

    /**
     * 得到单个站点信息面板
     * @param station 输入站点
     * @return 站点信息面板
     */
    public JPanel getStationPane(MetroStation station) {
        stationPane = new JPanel();
        stationPane.setLayout(new GridBagLayout());
        stationTablePane = new StationTableToolPane(this, station);
        stationTable = new StationTable(this, station);
        stationPane.add(stationTablePane, new GBC(0, 0).setWeight(100, 0).setFill(GBC.BOTH));
        stationPane.add(new JScrollPane(stationTable), new GBC(0, 1).setWeight(100, 100).setFill(GBC.BOTH));
        currentElement = station;
        return stationPane;
    }

    /**
     * 得到单个关联信息面板
     * @param edge 输入关联
     * @return 关联信息面板
     */
    public JPanel getEdgePane(MetroEdge edge) {
        edgePane = new JPanel();
        edgePane.setLayout(new GridBagLayout());
        edgeTablePane = new EdgeTableToolPane(this, edge);
        edgeTable = new EdgeTable(this, edge);
        edgePane.add(edgeTablePane, new GBC(0, 0).setWeight(100, 0).setFill(GBC.BOTH));
        edgePane.add(new JScrollPane(edgeTable), new GBC(0, 1).setWeight(100, 100).setFill(GBC.BOTH));
        currentElement = edge;
        return edgePane;
    }

    public CalculPane newCalculPane() {
        calculPane = new CalculPane(frame);
        return calculPane;
    }

    /**
     * 得到计算窗体
     * @return 计算窗体
     */
    public CalculPane getCalCulPane() {
        if (calculPane == null) {
            calculPane = new CalculPane(frame);
        }
        return calculPane;
    }

    /**
     * 
     * @param o
     * @param arg
     */
    public void update(Observable o, Object arg) {
        if (o instanceof ElementManager) {
            int tElemTab = elemTab;
            removeAll();
            addTabs();
            elemTab = tElemTab;
            try {
                setFocus(elemTab, currentElement);
            } catch (InformationPanelException ex) {
                ex.printStackTrace();
            }
        }
    }
    private MetroFrame frame;
    private NameMap nameMap;
    private JPanel allLinePane;
    private JPanel allStationPane;
    private JPanel allEdgePane;
    private JPanel linePane;
    private JPanel stationPane;
    private JPanel edgePane;
    private CalculPane calculPane;
    private AllLineTableToolPane allLineTablePane;
    private AllStationTableToolPane allStationTablePane;
    private AllEdgeTableToolPane allEdgeTablePane;
    private LineTableToolPane lineTablePane;
    private StationTableToolPane stationTablePane;
    private EdgeTableToolPane edgeTablePane;
    private AllLineTable allLineTable;
    private AllStationTable allStationTable;
    private AllEdgeTable allEdgeTable;
    private LineTable lineTable;
    private StationTable stationTable;
    private EdgeTable edgeTable;
    private MetroElement currentElement;
    private int elemTab;
    /**
     * 窗口无额外窗口
     */
    public static final int INF_NULL = -1;
    /**
     * 全体线路窗口
     */
    public static final int ALL_LINE = 0;
    /**
     * 全体站点窗口
     */
    public static final int ALL_STATION = 1;
    /**
     * 全体关联窗体
     */
    public static final int ALL_EDGE = 2;
    /**
     * 额外窗体,包括线路、站点、关联、计算
     */
    public static final int EXTAB = 3;
    /**
     * 额外线路窗体
     */
    public static final int LINE = 4;
    /**
     * 额外站点窗体
     */
    public static final int STATION = 5;
    /**
     * 额外关联窗体
     */
    public static final int EDGE = 6;
    /**
     * 额外计算窗体
     */
    public static final int CALCUL = 7;
}
/*
 * 监听用户或软件的Tab的按键变化,向Tab自身发出信息
 */

class TabChangeListener implements ChangeListener {

    public void stateChanged(ChangeEvent e) {
        InformationPane pane = (InformationPane) e.getSource();
        int selectedIndex = pane.getSelectedIndex();

        if (selectedIndex == InformationPane.ALL_LINE) {
            pane.setHighLight(null, false);
            pane.removeExTab();
            pane.setElemTab(InformationPane.ALL_LINE);
            ModelManager.getInstance().setModel(false);
        } else if (selectedIndex == InformationPane.ALL_STATION) {
            pane.setHighLight(null, false);
            pane.removeExTab();
            pane.setElemTab(InformationPane.ALL_STATION);
            ModelManager.getInstance().setModel(false);
        } else if (selectedIndex == InformationPane.ALL_EDGE) {
            pane.setHighLight(null, false);
            pane.removeExTab();
            pane.setElemTab(InformationPane.ALL_EDGE);
            ModelManager.getInstance().setModel(false);
        } else if (selectedIndex == InformationPane.EXTAB) {
            pane.setHighLight(pane.getElement(), true);
        }
    }
}